package cn.labbook.bluetooth.util;

import cn.labbook.bluetooth.annotation.ExcelOutName;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2017/10/17.
 */
public class ExcelWriter extends ReflectBase {


    private static volatile ExcelWriter excelWriter;


    public ExcelWriter() {

    }

    public static ExcelWriter getDefaultExcelWriter() {

        if (excelWriter == null) {
            synchronized (ExcelWriter.class) {
                if (excelWriter == null) {
                    excelWriter = new ExcelWriter();
                }
            }
        }
        return excelWriter;
    }

    //只需要数据
    public <V> HSSFWorkbook write(Class<V> clazz, List<V> list) throws Exception {
        return write(clazz, list, "sheet1", null);
    }

    //需要数据和
    public <V> HSSFWorkbook write(Class<V> clazz, List<V> list, Map<String, String> excelNameMap) throws Exception {
        return write(clazz, list, "sheet1", excelNameMap);
    }

    public <V> HSSFWorkbook write(Class<V> clazz, List<V> list, String sheetName) throws Exception {
        return write(clazz, list, sheetName, null);
    }


    /**
     * @param clazz
     * @param list
     * @param sheetName
     * @param <V>
     * @return
     * @throws Exception
     */
    public <V> HSSFWorkbook write(Class<V> clazz, List<V> list,
                                  String sheetName, Map<String, String> excelNameMap) throws Exception {

        HSSFWorkbook wb = new HSSFWorkbook();
        //设置单元格格式
        HSSFCellStyle style = wb.createCellStyle();
        HSSFDataFormat format = wb.createDataFormat();
        style.setDataFormat(format.getFormat("@"));//文本
        style.setAlignment(HSSFCellStyle.ALIGN_LEFT);//居中

        Sheet sheet = wb.createSheet(sheetName);

        Field[] fields = clazz.getDeclaredFields();

        Row row = sheet.createRow(0);
        //生成excel表头
        for (int i = 0; i < fields.length; i++) {

            Cell cell = row.createCell(i);
            //如果传入的map是null 使用fieldName 否则将根据map对应的value
            String fieldName = fields[i].getName();
            String excelName = excelNameMap == null ? null : excelNameMap.get(fieldName);

            String outName = excelName == null ? fieldName : excelName;

            ExcelOutName annotation = fields[i].getAnnotation(ExcelOutName.class);
            outName = annotation != null ? annotation.value() : outName;

            cell.setCellValue(outName);
            sheet.setDefaultColumnStyle(i, style);
            sheet.setColumnWidth((short) i, (short) (35.7 * 200));
        }
        //生成数据

        if (list == null || list.isEmpty()) return wb;//为空直接返回表头

        for (int i = 1; i <= list.size(); i++) {
            V v = list.get(i - 1);
            Row contentRow = sheet.createRow(i);
            for (int j = 0; j < fields.length; j++) {

                //利用反射取值
                Cell cell = contentRow.createCell(j);
                String fieldName = fields[j].getName();

                //用get
                String methodName = fieldNameToMethodName(GET, fieldName);

                Method method = clazz.getMethod(methodName);

                Object invoke = method.invoke(v);

                cell.setCellStyle(style);//设置单元格格式为"文本"
                cell.setCellType(HSSFCell.CELL_TYPE_STRING);

                setCellValue(cell, invoke);
            }
        }


        return wb;
    }


    private void setCellValue(Cell cell, Object invoke) {

        if (invoke instanceof Integer) {
            cell.setCellValue((Integer) invoke);
        } else if (invoke instanceof Date) {
            cell.setCellValue((Date) invoke);
        } else if (invoke instanceof String) {
            cell.setCellValue((String) invoke);
        } else if (invoke instanceof Double) {
            cell.setCellValue((Double) invoke);
        } else if (invoke instanceof Boolean) {
            cell.setCellValue((Boolean) invoke);
        } else if (invoke instanceof RichTextString) {
            cell.setCellValue((RichTextString) invoke);
        } else if (invoke instanceof Calendar) {
            cell.setCellValue((Calendar) invoke);
        }
    }


}
